package com.mengxiangnongfu.controller.system;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.mengxiangnongfu.aspectj.annotation.Log;
import com.mengxiangnongfu.aspectj.enums.BusinessType;
import com.mengxiangnongfu.config.utils.ShiroSecurityUtils;
import com.mengxiangnongfu.config.vo.ActiveUser;
import com.mengxiangnongfu.constants.Constants;
import com.mengxiangnongfu.constants.HttpStatus;
import com.mengxiangnongfu.domain.LoginInfo;
import com.mengxiangnongfu.domain.Menu;
import com.mengxiangnongfu.domain.SimpleUser;
import com.mengxiangnongfu.dto.LoginBodyDto;
import com.mengxiangnongfu.service.LoginInfoService;
import com.mengxiangnongfu.service.MenuService;
import com.mengxiangnongfu.utils.AddressUtils;
import com.mengxiangnongfu.utils.IpUtils;
import com.mengxiangnongfu.vo.AjaxResult;
import com.mengxiangnongfu.vo.MenuTreeVo;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 登录
 */
@RestController
@Slf4j
@Api(value = "登录")
public class LoginController {

    @Resource
    private MenuService menuService;

    @Resource
    private LoginInfoService loginInfoService;

    /**
     * 用户登录
     *
     * @param httpServletRequest
     * @param loginBodyDto
     * @return
     */
    @PostMapping("login/doLogin")
    public AjaxResult login(@Validated @RequestBody LoginBodyDto loginBodyDto, HttpServletRequest httpServletRequest) {
        AjaxResult ajaxResult = AjaxResult.success();
        String username = loginBodyDto.getUsername();
        String password = loginBodyDto.getPassword();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //构造用户名和密码的token对象
        Subject subject = SecurityUtils.getSubject();
        LoginInfo loginInfo = createLoginInfo(httpServletRequest);
        try {
            subject.login(token);
            Serializable webToken = subject.getSession().getId();
            ajaxResult.put(Constants.TOKEN, webToken);
            loginInfo.setMsg("登录成功");
            loginInfo.setLoginStatus(Constants.LOGIN_SUCCESS);
            loginInfo.setLoginAccount(loginBodyDto.getUsername());
            loginInfo.setUserName(ShiroSecurityUtils.getCurrentActiveUser().getUser().getUserName());
        } catch (Exception ex) {
            loginInfo.setMsg("登录失败");
            loginInfo.setLoginStatus(Constants.LOGIN_ERROR);
            loginInfo.setLoginAccount(loginBodyDto.getUsername());
        }
        loginInfoService.insertLoginInfoLog(loginInfo);
        return ajaxResult;
    }

    /**
     * 获取用户信息
     *
     * @return
     */
    @GetMapping("login/getInfo")
    public AjaxResult getInfo() {
        Subject subject = SecurityUtils.getSubject();
        ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
        AjaxResult ajax = AjaxResult.success();
        ajax.put("username", activeUser.getUser().getUserName());
        ajax.put("picture", activeUser.getUser().getPicture());
        ajax.put("roles", activeUser.getRoles());
        ajax.put("permissions", activeUser.getPermissions());
        return ajax;
    }

    /**
     * 退出
     *
     * @return
     */
    @GetMapping("login/logout")
    public AjaxResult logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        AjaxResult ajaxResult = AjaxResult.success("退出成功!");
        return ajaxResult;
    }

    /**
     * 获取当前用户的菜单
     *
     * @return
     */
    @GetMapping("login/getMenu")
    public AjaxResult getMenus() {
        Subject subject = SecurityUtils.getSubject();
        ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
        boolean isAdmin = activeUser.getUser().getUserType().equals(Constants.USER_ADMIN);
        SimpleUser simpleUser = null;
        if (!isAdmin) {
            simpleUser = new SimpleUser(activeUser.getUser().getUserId(), activeUser.getUser().getUserName());
        }
        List<Menu> menuList = menuService.selectMenuTree(isAdmin, simpleUser);
        List<MenuTreeVo> menuTreeVos = new ArrayList<>();
        for (Menu menu : menuList) {
            menuTreeVos.add(new MenuTreeVo(menu.getMenuId().toString(), menu.getPath()));
        }
        return AjaxResult.success(menuTreeVos);
    }

    /**
     * 构造登录时内部的参数
     *
     * @param request
     * @return
     */
    private LoginInfo createLoginInfo(HttpServletRequest request) {
        UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setOs(userAgent.getOs().toString());
        loginInfo.setBrowser(userAgent.getBrowser().toString());
        loginInfo.setLoginTime(DateUtil.date());
        loginInfo.setLoginType(Constants.LOGIN_TYPE_SYSTEM);
        loginInfo.setIpAddr(IpUtils.getIpAddr(request));
        loginInfo.setLoginLocation(AddressUtils.getRealAddressByIP(IpUtils.getIpAddr(request)));
        return loginInfo;
    }
}
